use alice2d::{math::{Matrix4f, Vector3f}, scene::{ Camera, CameraType}};



pub struct EditorCamera {
    view: Matrix4f,
    projection: Matrix4f,
    view_projection: Matrix4f,
    pub position: Vector3f,
    pub rotation: f32,
    pub camera_type: CameraType,

}


impl Camera for EditorCamera {
    fn new_with_orthographic(left:f32,right:f32,bottom:f32,top:f32) -> Self {
        let projection = Matrix4f::orthographic(left,right,bottom,top, -1.0, 1.0);
   
        let view = Matrix4f::identity();
        let view_projection = Matrix4f::identity();
        let mut camera = Self {
            view,
            projection,
            view_projection,
            camera_type:        CameraType::Orthographic,
            position:           Vector3f::new(0.0, 0.0, 0.0),
            rotation:           0.0
        };
        camera.update_view();
        camera
    }

    fn new_with_perspective(fovy:f32, aspect:f32,znear:f32,zfar:f32) -> Self {
     
        let projection = Matrix4f::perspective(fovy, aspect,  znear, zfar);
    
        let view = Matrix4f::identity();
        let view_projection = Matrix4f::identity();
        let mut camera = Self {
            view,
            projection,
            view_projection,
            camera_type: CameraType::Perspective,
            rotation:           0.0,
            position: Vector3f::new(0.0, 0.0, 0.0),
        };
        camera.update_view();
        camera
    }

    fn update_view(&mut self) {
        let position = Matrix4f::new_translation(&self.position);
        let rotation = Matrix4f::new_rotation(&Vector3f::new(0.0, 0.0, self.rotation));
        let transform = position * rotation;
        self.view = transform.inverse();
     
        self.view_projection = self.projection * self.view;
    }

    fn get_view_projection(&self) -> Matrix4f {
        self.view_projection
    }

    fn get_camera_type(&self) -> CameraType {
        self.camera_type
    }

    fn get_view(&self) -> Matrix4f {
        self.view
    }

    fn get_projection(&self) -> Matrix4f {
        self.projection
    }
}

impl EditorCamera {
   
    pub fn set_position(&mut self , position:Vector3f) {
        if self.position != position {
            self.position = position;
            self.update_view();
        }
      
    }

    pub fn set_rotation(&mut self , rotation:f32) {
        if self.rotation != rotation {
            self.rotation = rotation;
            self.update_view();
        }
       
    }

    pub fn set_projection(&mut self , left:f32,right:f32,bottom:f32,top:f32) {
        self.projection = Matrix4f::orthographic(left,right,bottom,top, -1.0, 1.0);
        self.update_view();
    }
}

